#include "ekk_player/ekk_queue.h"
#ifndef EKK_INTERFACE_H_
#include <stdlib.h>
#include <string.h>
#define ekk_malloc malloc
#define ekk_free free
#define ekk_memset memset
#endif

#define DEFAULT_MAX_QUEUE 50

typedef struct tag_queue{
	void** array;
	volatile int h;
	volatile int t;
	int max_size;
}QUEUE,*PQUEUE;

int ekk_queue_get_max_size(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	return pq->max_size - 1;
}

int ekk_queue_set_max_size(QUEUE_HANDLE hq,int sz)
{
	QUEUE* pq = (QUEUE*)hq;
	if (sz == 0)
	{
		sz = DEFAULT_MAX_QUEUE;
	}
	pq->max_size = sz + 1;
	return pq->max_size;
}

QUEUE_HANDLE ekk_queue_create()
{
	QUEUE* pq = (QUEUE*)ekk_malloc(sizeof(QUEUE));
	ekk_memset(pq,0,sizeof(QUEUE));
	pq->max_size = DEFAULT_MAX_QUEUE + 1;
	return (QUEUE_HANDLE)pq;
}

void ekk_queue_clean(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	while (ekk_queue_get_len(hq) > 0)
	{
		ekk_queue_pop(hq);
	}
	if(pq->array)
	{
		ekk_free(pq->array);
		pq->array = 0;
	}
}

void ekk_queue_destroy(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	ekk_queue_clean(hq);
	ekk_free(pq);
}

int ekk_queue_get_len(QUEUE_HANDLE hq)
{
	int h,t;
	QUEUE* pq = (QUEUE*)hq;
	h = pq->h;
	t = pq->t;
	return h>t ? (t+pq->max_size-h) : (t-h);
}

void* ekk_queue_pop(QUEUE_HANDLE hq)
{
	int h,t,rt;
	void* ret = 0;
	QUEUE* pq = (QUEUE*)hq;
	h = pq->h;
	t = pq->t;
	rt = (t >= h ? t : t + pq->max_size);
	if(rt - h <= 0)
	{
		ret = 0;
	}
	else
	{
		ret = pq->array[h];
		pq->h = (h+1) % pq->max_size;
	}
	return ret;
}
//add by zzw
void* ekk_queue_pre_pop(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	int t = pq->h;
	if(ekk_queue_get_len(hq) <= 0)
		return 0;	
	return pq->array[t];
}

void ekk_queue_alloc(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	if (!pq->array)
	{
		pq->array = ekk_malloc(sizeof(void*)*pq->max_size);
	}
}

void ekk_queue_push(QUEUE_HANDLE hq,void* p)
{
	int h,t,rt;
	QUEUE* pq = (QUEUE*)hq;
	t = pq->t;
	h = pq->h;
	rt = (t >= h ? t : t + pq->max_size);
	if (rt + 1 - h < pq->max_size)
	{
		pq->array[t] = p;
		pq->t = (t+1) % pq->max_size;
	}
}

int ekk_queue_is_full(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	return ekk_queue_get_len(hq) >= (pq->max_size - 1) ? 1 : 0;
}

int ekk_queue_is_empty(QUEUE_HANDLE hq)
{
	QUEUE* pq = (QUEUE*)hq;
	return ekk_queue_get_len(hq) >0 ? 0 : 1;
}